#!/bin/bash

# 生产环境部署脚本
set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
ENVIRONMENT=${1:-prod}
BACKUP_DIR="${PROJECT_DIR}/backup"
LOG_FILE="${PROJECT_DIR}/deploy.log"

# 日志函数
log() {
    echo -e "$1" | tee -a "$LOG_FILE"
}

log_info() {
    log "${BLUE}[INFO $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_success() {
    log "${GREEN}[SUCCESS $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_warning() {
    log "${YELLOW}[WARNING $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_error() {
    log "${RED}[ERROR $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

# 错误处理
trap 'log_error "部署过程中发生错误，正在回滚..."; rollback; exit 1' ERR

# 显示帮助信息
show_help() {
    echo "教案管理平台部署脚本"
    echo ""
    echo "用法: $0 [options]"
    echo ""
    echo "选项:"
    echo "  prod              部署到生产环境 (默认)"
    echo "  test              部署到测试环境"
    echo "  --backup          部署前备份数据库"
    echo "  --no-build        跳过构建步骤"
    echo "  --health-check    只进行健康检查"
    echo "  --rollback        回滚到上一个版本"
    echo "  --help            显示此帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 prod --backup    # 备份数据库后部署到生产环境"
    echo "  $0 --rollback       # 回滚到上一个版本"
    echo "  $0 --health-check   # 进行健康检查"
}

# 检查依赖
check_dependencies() {
    log_info "检查部署依赖..."
    
    local deps=("docker" "docker-compose" "curl" "git")
    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            log_error "缺少依赖: $dep"
            exit 1
        fi
    done
    
    log_success "依赖检查通过"
}

# 环境检查
check_environment() {
    log_info "检查环境配置..."
    
    # 检查环境文件
    if [ ! -f ".env.${ENVIRONMENT}" ]; then
        log_error "环境文件 .env.${ENVIRONMENT} 不存在"
        log_info "运行: ./scripts/env-setup.sh ${ENVIRONMENT}"
        exit 1
    fi
    
    # 加载环境变量
    source ".env.${ENVIRONMENT}"
    
    # 检查必需变量
    local required_vars=("MONGO_ROOT_PASSWORD" "JWT_SECRET" "DOMAIN_NAME")
    for var in "${required_vars[@]}"; do
        if [ -z "${!var}" ]; then
            log_error "环境变量 $var 未设置"
            exit 1
        fi
    done
    
    log_success "环境检查通过"
}

# 创建备份
create_backup() {
    if [ "$BACKUP" = true ]; then
        log_info "创建数据库备份..."
        
        mkdir -p "$BACKUP_DIR"
        BACKUP_FILE="$BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S).gz"
        
        docker-compose -f docker-compose.prod.yml exec -T mongodb mongodump \
            --username="${MONGO_ROOT_USERNAME}" \
            --password="${MONGO_ROOT_PASSWORD}" \
            --authenticationDatabase=admin \
            --db="${MONGO_DATABASE}" \
            --gzip \
            --archive > "$BACKUP_FILE"
        
        log_success "备份已创建: $BACKUP_FILE"
    fi
}

# 构建镜像
build_images() {
    if [ "$NO_BUILD" != true ]; then
        log_info "构建Docker镜像..."
        
        # 构建后端镜像
        docker build -f backend/Dockerfile.prod -t lesson-plan-backend:latest ./backend
        
        # 构建前端镜像
        docker build -f frontend/Dockerfile.prod -t lesson-plan-frontend:latest ./frontend
        
        log_success "镜像构建完成"
    else
        log_info "跳过构建步骤"
    fi
}

# 部署服务
deploy_services() {
    log_info "部署服务..."
    
    # 停止旧服务
    docker-compose -f docker-compose.prod.yml down --remove-orphans
    
    # 启动新服务
    docker-compose -f docker-compose.prod.yml up -d
    
    log_success "服务部署完成"
}

# 健康检查
health_check() {
    log_info "进行健康检查..."
    
    local max_attempts=30
    local attempt=1
    
    # 等待服务启动
    sleep 10
    
    # 检查后端健康状态
    while [ $attempt -le $max_attempts ]; do
        if curl -f http://localhost:3001/health &> /dev/null; then
            log_success "后端服务健康检查通过"
            break
        fi
        
        log_info "等待后端服务启动... ($attempt/$max_attempts)"
        sleep 10
        ((attempt++))
    done
    
    if [ $attempt -gt $max_attempts ]; then
        log_error "后端服务健康检查失败"
        return 1
    fi
    
    # 检查前端健康状态
    if curl -f http://localhost &> /dev/null; then
        log_success "前端服务健康检查通过"
    else
        log_error "前端服务健康检查失败"
        return 1
    fi
    
    # 检查数据库连接
    if docker-compose -f docker-compose.prod.yml exec -T mongodb mongo --eval "db.adminCommand('ping')" &> /dev/null; then
        log_success "数据库健康检查通过"
    else
        log_error "数据库健康检查失败"
        return 1
    fi
    
    log_success "所有服务健康检查通过"
}

# 回滚
rollback() {
    log_warning "开始回滚..."
    
    # 停止当前服务
    docker-compose -f docker-compose.prod.yml down
    
    # 从备份恢复（如果有）
    local latest_backup=$(ls -t "$BACKUP_DIR"/backup-*.gz 2>/dev/null | head -n1)
    if [ -n "$latest_backup" ]; then
        log_info "从备份恢复: $latest_backup"
        
        docker-compose -f docker-compose.prod.yml up -d mongodb
        sleep 10
        
        docker-compose -f docker-compose.prod.yml exec -T mongodb mongorestore \
            --username="${MONGO_ROOT_USERNAME}" \
            --password="${MONGO_ROOT_PASSWORD}" \
            --authenticationDatabase=admin \
            --drop \
            --gzip \
            --archive < "$latest_backup"
    fi
    
    log_success "回滚完成"
}

# 清理
cleanup() {
    log_info "清理无用的Docker资源..."
    
    docker system prune -f
    docker image prune -f
    
    log_success "清理完成"
}

# 主函数
main() {
    cd "$PROJECT_DIR"
    
    # 创建日志文件
    touch "$LOG_FILE"
    
    log_info "开始部署到 $ENVIRONMENT 环境..."
    log_info "项目目录: $PROJECT_DIR"
    
    # 检查依赖和环境
    check_dependencies
    check_environment
    
    # 创建备份
    create_backup
    
    # 构建和部署
    build_images
    deploy_services
    
    # 健康检查
    health_check
    
    # 清理
    cleanup
    
    log_success "部署完成！"
    log_info "应用访问地址: http://${DOMAIN_NAME}"
    log_info "部署日志: $LOG_FILE"
}

# 解析命令行参数
BACKUP=false
NO_BUILD=false
HEALTH_CHECK_ONLY=false
ROLLBACK=false

while [[ $# -gt 0 ]]; do
    case $1 in
        --backup)
            BACKUP=true
            shift
            ;;
        --no-build)
            NO_BUILD=true
            shift
            ;;
        --health-check)
            HEALTH_CHECK_ONLY=true
            shift
            ;;
        --rollback)
            ROLLBACK=true
            shift
            ;;
        --help)
            show_help
            exit 0
            ;;
        prod|test)
            ENVIRONMENT=$1
            shift
            ;;
        *)
            log_error "未知选项: $1"
            show_help
            exit 1
            ;;
    esac
done

# 执行对应操作
if [ "$HEALTH_CHECK_ONLY" = true ]; then
    health_check
elif [ "$ROLLBACK" = true ]; then
    check_dependencies
    check_environment
    rollback
else
    main
fi